package com.wh1200.mybatis.xmlless.resolver

import com.wh1200.mybatis.xmlless.config.BaseResolverTest
import com.wh1200.mybatis.xmlless.model.ConditionConnector
import com.wh1200.mybatis.xmlless.model.component.ExpressionGroup
import com.wh1200.mybatis.xmlless.model.component.StringExpression
import com.wh1200.xmlless.test.dao.StudentDAO
import net.sf.jsqlparser.parser.CCJSqlParserUtil
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import kotlin.reflect.jvm.javaMethod
import kotlin.test.assertEquals
import kotlin.test.assertIs
import kotlin.test.assertNotNull

/**
 * Created by 吴昊 on 2023/12/22.
 */
class CriteriaResolverTest : BaseResolverTest(StudentDAO::class.java) {

  @Test
  @DisplayName("in一个常量")
  fun parseExpression() {
    val res = CriteriaResolver.parseExpression(
        "a = b and a in (1,2,3)"
    )
    println(res)
    val res2 = CriteriaResolver.parseExpression(
        "a between b and c"
    )
    assert(res2 is StringExpression)
  }

  @Test
  @DisplayName("复杂的条件分组")
  fun parseExpression5() {
    val str = "(a is not null and (b is null or c is null)) OR (d is null and (e is not null or f is not null))"
    val exp = CriteriaResolver.parseExpression(str)
    assertIs<ExpressionGroup>(exp)
    assertEquals(2, exp.expressions.size)
    assertEquals(ConditionConnector.OR, exp.connector)
  }

  @Test
  @DisplayName("包含between and")
  fun parseExpression2() {
    val res3 = CriteriaResolver.parseExpression(
        "a between b and c and d = e"
    )
    assert(res3 is ExpressionGroup)
    res3 as ExpressionGroup
    assertEquals(2, res3.expressions.size)
    val first = res3.expressions.first()
    first as StringExpression
    assert(first.tokens.any { it.toSql() == "and" && it::class.java.simpleName == "Operator" })
  }

  @Test
  fun resolveConditions() {
    val methodInfo = createMethodInfo(StudentDAO::find4.javaMethod!!)
    val exp = CriteriaResolver.parseExpression("date(createTime) >= date(start)")
    exp as StringExpression
    val op = exp.tokens.find { it::class.java.simpleName == "Operator" }
    assertNotNull(op)
    println(exp)
    CriteriaResolver.resolveConditionsFromExpression("date(createTime) >= date(start)", methodInfo)
  }

  @Test
  fun testResolveConditions() {
    val methodInfo = createMethodInfo(StudentDAO::find4.javaMethod!!)
    CriteriaResolver.resolveConditionsFromExpression("name like keywords", methodInfo)
  }

  @Test
  fun createComplexParameterCondition() {
    val methodInfo = createMethodInfo(StudentDAO::find4.javaMethod!!)
    CriteriaResolver.createComplexParameterCondition(methodInfo)
  }

  @Test
  fun chooseFromParameter() {
  }

  @Test
  fun resolveCriteria() {
    val methodInfo = createMethodInfo(StudentDAO::find4.javaMethod!!)
    val result = CriteriaResolver.resolveCriteria(
        listOf("UpdateUserId", "Eq", "CurrentUserId"),
        methodInfo, ValueHolder(0)
    )
    val tests = result.getTests(null)
    println(tests)
    println(result)
  }

  @Test
  fun resolveCriteriaFromProperty() {
    val sql = """SELECT
  parent_id_t_server.ip AS ip,
  parent_id_t_server.name AS name,
  provider_id_t_server_provider.id AS provider_id,
  provider_id_t_server_provider.name AS provider_name,
  t_server."order" AS `order`,
  t_server.id AS id,
  t_server.ip AS ip,
  t_server.name AS name,
  t_server.parent_id AS parentId,
  t_server.provider_id AS providerId
FROM
  t_server
LEFT JOIN
    t_server parent_id_t_server
  ON
    parent_id_t_server.id = t_server.parent_id
LEFT JOIN
    t_server_provider provider_id_t_server_provider
  ON
    provider_id_t_server_provider.id = t_server.provider_id
WHERE
  t_server.name = 'a'"""
    CCJSqlParserUtil.parse(sql)
  }

}
